---
title: Comments
icon: MessageSquareMore
---

import { IconWrapper } from '@/components/icon-wrapper'

<MetaData
  lang="en-US"
  meta={{
    preset: [{
      client: '@univerjs/preset-sheets-thread-comment',
      locale: '@univerjs/preset-sheets-thread-comment/locales/en-US',
      style: '@univerjs/preset-sheets-thread-comment/lib/index.css',
    }],
    plugins: [{
      client: '@univerjs/thread-comment',
    }, {
      client: '@univerjs/thread-comment-ui',
      locale: '@univerjs/thread-comment-ui/locale/en-US',
      style: '@univerjs/thread-comment-ui/lib/index.css',
    }, {
      client: '@univerjs/sheets-thread-comment',
      facade: '@univerjs/sheets-thread-comment/facade',
    }, {
      client: '@univerjs/sheets-thread-comment-ui',
      locale: '@univerjs/sheets-thread-comment-ui/locale/en-US',
      style: '@univerjs/sheets-thread-comment-ui/lib/index.css',
    }],
    server: 'Optional',
  }}
/>

Comments allow users to add comments and replies within documents, facilitating communication and collaboration among team members.

## Preset Mode

### Installation

```package-install
npm install @univerjs/preset-sheets-thread-comment
```

### Usage

```typescript
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'
import { UniverSheetsThreadCommentPreset } from '@univerjs/preset-sheets-thread-comment' // [!code ++]
import UniverPresetSheetsThreadCommentEnUS from '@univerjs/preset-sheets-thread-comment/locales/en-US' // [!code ++]
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'

import '@univerjs/preset-sheets-core/lib/index.css'
import '@univerjs/preset-sheets-thread-comment/lib/index.css' // [!code ++]

const { univerAPI } = createUniver({
  locale: LocaleType.En_US,
  locales: {
    [LocaleType.En_US]: mergeLocales(
      UniverPresetSheetsCoreEnUS,
      UniverPresetSheetsThreadCommentEnUS, // [!code ++]
    ),
  },
  presets: [
    UniverSheetsCorePreset(),
    UniverSheetsThreadCommentPreset(), // [!code ++]
  ],
})
```

#### Using with Collaboration Feature <IconWrapper className="inline-flex" type="pro" size="xs" icon={null} />

If you are using the [collaboration](/guides/sheets/features/collaboration) feature with `UniverSheetsCollaborationPreset`, make sure to pass the `collaboration: true` option in `UniverSheetsThreadCommentPreset`:

```typescript
UniverSheetsThreadCommentPreset({
  collaboration: true, // [!code ++]
})
```

{/* ### Presets and Configuration */}

## Plugin Mode

### Installation

```package-install
npm install @univerjs/thread-comment @univerjs/thread-comment-ui @univerjs/sheets-thread-comment @univerjs/sheets-thread-comment-ui
```

### Usage

```typescript
import { LocaleType, mergeLocales, Univer } from '@univerjs/core'
import { UniverSheetsThreadCommentPlugin } from '@univerjs/sheets-thread-comment' // [!code ++]
import { UniverSheetsThreadCommentUIPlugin } from '@univerjs/sheets-thread-comment-ui' // [!code ++]
import SheetsThreadCommentUIEnUS from '@univerjs/sheets-thread-comment-ui/locale/en-US' // [!code ++]
import { UniverThreadCommentPlugin } from '@univerjs/thread-comment' // [!code ++]
import { UniverThreadCommentUIPlugin } from '@univerjs/thread-comment-ui' // [!code ++]
import ThreadCommentUIEnUS from '@univerjs/thread-comment-ui/locale/en-US' // [!code ++]

import '@univerjs/thread-comment-ui/lib/index.css' // [!code ++]

import '@univerjs/sheets-thread-comment/facade' // [!code ++]

const univer = new Univer({
  locale: LocaleType.En_US,
  locales: {
    [LocaleType.En_US]: mergeLocales(
      ThreadCommentUIEnUS, // [!code ++]
      SheetsThreadCommentUIEnUS, // [!code ++]
    ),
  },
})

univer.registerPlugin(UniverThreadCommentPlugin) // [!code ++]
univer.registerPlugin(UniverThreadCommentUIPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsThreadCommentPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsThreadCommentUIPlugin) // [!code ++]
```

#### Using with Collaboration Feature <IconWrapper className="inline-flex" type="pro" size="xs" icon={null} />

If you are using the [collaboration](/guides/sheets/features/collaboration) feature, configure it as follows:

```package-install
npm install @univerjs-pro/thread-comment-datasource
```

```typescript
import { UniverThreadCommentDataSourcePlugin } from '@univerjs-pro/thread-comment-datasource' // [!code ++]

univer.registerPlugin(UniverThreadCommentDataSourcePlugin) // [!code ++]
```

{/* ### Plugins and Configuration */}

## Facade API

Complete Facade API type definitions can be found in the [FacadeAPI](https://reference.univer.ai/en-US).

### Create Cell Comment

You can create a new comment builder using `univerAPI.newTheadComment()`, which returns an instance of `FTheadCommentBuilder`. You can chain methods to set various properties of the comment.

The following are some member methods of [`FTheadCommentBuilder`](https://reference.univer.ai/en-US/classes/FTheadCommentBuilder):

| Method | Description |
| ---- | ---- |
| setContent | Set the content of the comment |
| setPersonId | Set the person ID for the comment |
| setDateTime | Set the date and time of the comment |
| setId | Set the ID of the comment |
| setThreadId | Set the thread ID of the comment |

```typescript
// Create a new comment
const richText = univerAPI.newRichText().insertText('hello univer')
const commentBuilder = univerAPI.newTheadComment()
  .setContent(richText)

console.log(commentBuilder.content.toPlainText())

// Add the comment to cell A1
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const cell = fWorksheet.getRange('A1')
const result = await cell.addCommentAsync(commentBuilder)
```

### Get Cell Comments

You can retrieve comments using the following methods, which return an instance of `FThreadComment`. You can then perform operations such as updating, deleting, or resolving the comment.

- `FWorkbook.getComments()`: Get all comments in the workbook
- `FWorksheet.getComments()`: Get all comments in the worksheet
- `FRange.getComment()`: Get the comment of the top-left cell in the range
- `FRange.getComments()`: Get all comments in the range

The following are some member methods of [`FThreadComment`](https://reference.univer.ai/en-US/classes/FThreadComment):

| Method | Description |
| ---- | ---- |
| getIsRoot | Whether the comment is a root comment |
| getCommentData | Get the comment data |
| getReplies | Get the list of replies to the comment |
| getRange | Get the range of the comment |
| getRichText | Get the rich text content of the comment |
| deleteAsync | Delete the comment and its replies |
| updateAsync | Update the content of the comment |
| resolveAsync | Resolve the comment |
| replyAsync | Reply to the comment |

```typescript
// Get all comments in the workbook
const fWorkbook = univerAPI.getActiveWorkbook()
fWorkbook.getComments()

// Get all comments in the active worksheet
const fWorksheet = fWorkbook.getActiveSheet()
Worksheet.getComments()

const fRange = fWorksheet.getRange('A1:B2')
// Get the comment of cell A1
fRange.getComment()

// Get all comments in the range A1:B2
fRange.getComments()
```

### Clear Cell Comments

- `FWorkbook.clearComments()`: Clear all comments in the workbook
- `FWorksheet.clearComments()`: Clear all comments in the worksheet
- `FRange.clearCommentAsync()`: Clear the comment of the top-left cell in the range
- `FRange.clearCommentsAsync()`: Clear all comments in the range

```typescript
// Clear all comments in the workbook
const fWorkbook = univerAPI.getActiveWorkbook()
await fWorkbook.clearComments()

// Clear all comments in the active worksheet
const fWorksheet = fWorkbook.getActiveSheet()
await fWorksheet.clearComments()

const fRange = fWorksheet.getRange('A1:B2')

// Clear the comment of cell A1
await fRange.clearCommentAsync()

// Clear all comments in the range A1:B2
await fRange.clearCommentsAsync()
```

### Get Comment Replies List

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Get all comments in the worksheet
const comments = fWorksheet.getComments()
comments.forEach((comment) => {
  // If the comment is a root comment, get its replies
  if (comment.getIsRoot()) {
    const replies = comment.getReplies()
    replies.forEach((reply) => {
      console.log(reply.getCommentData())
    })
  }
})
```

### Update/Delete/Resolve/Reply to Comments

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// Create a new comment and add it to cell A1
const richText = univerAPI.newRichText().insertText('hello univer')
const commentBuilder = univerAPI.newTheadComment()
  .setContent(richText)
  .setId('mock-comment-id')
const cell = fWorksheet.getRange('A1')
await cell.addCommentAsync(commentBuilder)

// Update the comment and reply after 3 seconds
setTimeout(async () => {
  // Get the comment by ID and update its content
  const comment = fWorksheet.getCommentById('mock-comment-id')
  const newRichText = univerAPI.newRichText().insertText('Hello Univer AI')
  await comment.updateAsync(newRichText)

  // Create a new reply comment and set its content
  const replyText = univerAPI.newRichText().insertText('Hello Univer AI! GO! GO! GO!')
  const reply = univerAPI.newTheadComment().setContent(replyText)
  await comment.replyAsync(reply)
}, 3000)

// Resolve the comment and delete it after 6 seconds
setTimeout(async () => {
  const comment = fWorksheet.getCommentById('mock-comment-id')
  await comment.resolveAsync()
  await comment.deleteAsync()
}, 6000)
```

### Event Listeners

Complete event type definitions can be found in [Events](https://reference.univer.ai/en-US/classes/FEventName).

The comment module provides a series of events to listen for comment additions, updates, deletions, and resolution status changes. All events can be listened to using `univerAPI.addEvent()`.

#### Comment Addition Events

`univerAPI.Event.CommentAdded`: Triggered after a comment is added

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.CommentAdded, (params) => {
  const { comment, workbook, worksheet, row, col } = params
})

// Remove the event listener, use `disposable.dispose()`
```

`univerAPI.Event.BeforeCommentAdd`: Triggered before a comment is added

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeCommentAdd, (params) => {
  const { comment, workbook, worksheet, row, col } = params

  // Cancel the comment addition operation
  params.cancel = true
})

// Remove the event listener, use `disposable.dispose()`
```

#### Comment Update Events

`univerAPI.Event.CommentUpdated`: Triggered after a comment is updated

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.CommentUpdated, (params) => {
  const { comment, workbook, worksheet, row, col } = params
})

// Remove the event listener, use `disposable.dispose()`
```

`univerAPI.Event.BeforeCommentUpdate`: Triggered before a comment is updated

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeCommentUpdate, (params) => {
  const { comment, workbook, worksheet, row, col, newContent } = params

  // Cancel the comment update operation
  params.cancel = true
})

// Remove the event listener, use `disposable.dispose()`
```

#### Comment Deletion Events

`univerAPI.Event.CommentDeleted`: Triggered after a comment is deleted

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.CommentDeleted, (params) => {
  const { commentId, workbook, worksheet } = params
})

// Remove the event listener, use `disposable.dispose()`
```

`univerAPI.Event.BeforeCommentDelete`: Triggered before a comment is deleted

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeCommentDelete, (params) => {
  const { comment, workbook, worksheet, row, col } = params

  // Cancel the comment deletion operation
  params.cancel = true
})

// Remove the event listener, use `disposable.dispose()`
```

#### Comment Resolution Status Events

`univerAPI.Event.CommentResolved`: Triggered after the resolution status of a comment changes

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.CommentResolved, (params) => {
  const { comment, row, col, resolved, workbook, worksheet } = params
})

// Remove the event listener, use `disposable.dispose()`
```

`univerAPI.Event.BeforeCommentResolve`: Triggered before the resolution status of a comment changes

```typescript
const disposable = univerAPI.addEvent(univerAPI.Event.BeforeCommentResolve, (params) => {
  const { comment, row, col, resolved, workbook, worksheet } = params

  // Cancel the comment resolution operation
  params.cancel = true
})

// Remove the event listener, use `disposable.dispose()`
```

All events contain the following common parameters:

- `workbook`: Current workbook instance
- `worksheet`: Current worksheet instance
- `row`: Row index of the comment
- `col`: Column index of the comment
- `comment`: Comment object (only `commentId` is included in deletion events)

Special parameters:

- `BeforeCommentUpdate` event includes `newContent`: New comment content (RichTextValue type)
- `CommentResolved` and `BeforeCommentResolve` events include `resolved`: Resolution status of the comment

All `Before` prefixed event callback functions can return `params.cancel = true` to prevent the corresponding operation.
